package com.ciccwm.log.util;

import com.ciccwm.log.context.TraceContext;

import java.util.UUID;
import java.util.function.Supplier;

/**
 * 链路ID工具类.
 * 提供链路ID的生成、获取、设置和移除等功能.
 * 链路ID用于在分布式系统中追踪请求的完整调用链.
 */
public final class TraceIdUtil {


    private TraceIdUtil() {
        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
    }

    /**
     * 生成链路ID.
     * 使用UUID生成一个唯一的链路ID，并移除其中的连字符.
     *
     * @return 生成的链路ID字符串
     */
    public static String generateTraceId() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 获取当前链路ID.
     * 从ThreadLocal中获取当前线程的链路ID.
     * 如果不存在则生成一个新的链路ID.
     *
     * @return 当前线程的链路ID
     */
    public static String getTraceId() {
        String traceId = TraceContext.getTraceId();
        if (traceId == null) {
            traceId = generateTraceId();
            TraceContext.setTraceId(traceId);
        }
        return traceId;
    }

    /**
     * 设置当前链路ID.
     * 将链路ID存储到ThreadLocal中.
     *
     * @param traceId 要设置的链路ID
     */
    public static void setTraceId(String traceId) {
        TraceContext.setTraceId(traceId);
    }

    /**
     * 移除当前链路ID.
     * 从ThreadLocal中移除当前线程的链路ID.
     */
    public static void removeTraceId() {
        TraceContext.removeTraceId();
    }

    /**
     * 使用指定的链路ID执行操作.
     * 在执行操作前设置链路ID，操作完成后移除链路ID.
     *
     * @param traceId 要使用的链路ID
     * @param operation 要执行的操作
     * @param <T> 操作返回值类型
     * @return 操作结果
     */
    public static <T> T executeWithTraceId(String traceId, Supplier<T> operation) {
        try {
            setTraceId(traceId);
            return operation.get();
        } finally {
            removeTraceId();
        }
    }

    /**
     * 使用指定的链路ID执行无返回值的操作.
     * 在执行操作前设置链路ID，操作完成后移除链路ID.
     *
     * @param traceId 要使用的链路ID
     * @param operation 要执行的操作
     */
    public static void executeWithTraceId(String traceId, Runnable operation) {
        try {
            setTraceId(traceId);
            operation.run();
        } finally {
            removeTraceId();
        }
    }
} 
